home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / Asuka / source / symbols.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-08-13  |  7.3 KB  |  306 lines

  1. #include "stdafx.h"
  2. #include <vd2/system/file.h>
  3. #include <vd2/system/zip.h>
  4. #include "symbols.h"
  5. #include <string>
  6. #include <list>
  7. #include <map>
  8.  
  9. class VDSymbolSourceLinkMap : public IVDSymbolSource {
  10. public:
  11.     ~VDSymbolSourceLinkMap();
  12.  
  13.     void Init(const wchar_t *filename);
  14.     const VDSymbol *LookupSymbol(sint64 addr);
  15.     const VDSection *LookupSection(sint64 addr);
  16.     void GetAllSymbols(vdfastvector<VDSymbol>&);
  17.     uint32 GetCodeGroupMask();
  18.     int GetSectionCount();
  19.     const VDSection *GetSection(int sec);
  20.     bool LookupLine(sint64 addr, const char *& filename, int& lineno);
  21.  
  22. protected:
  23.     void Init(IVDStream *pStream);
  24.  
  25.     uint32        mCodeSegments;
  26.  
  27.     typedef vdfastvector<VDSymbol> tSymbols;
  28.     tSymbols    mSymbols;
  29.     typedef std::vector<VDSection> tSections;
  30.     tSections mSections;
  31.  
  32.     typedef std::list<std::string> tLineStrings;
  33.     tLineStrings mLineStrings;
  34.  
  35.     typedef std::pair<const char *, int> tLineInfo;
  36.     typedef std::map<sint64, tLineInfo> tLineMap;
  37.     tLineMap mLineMap;
  38. };
  39.  
  40. IVDSymbolSource *VDCreateSymbolSourceLinkMap() {
  41.     return new VDSymbolSourceLinkMap;
  42. }
  43.  
  44. namespace {
  45.     bool findline(VDTextStream& textStream, const char *s) {
  46.         while(const char *line = textStream.GetNextLine()) {
  47.             if (strstr(line, s))
  48.                 return true;
  49.         }
  50.  
  51.         return false;
  52.     }
  53.  
  54.     struct SymbolSort {
  55.         bool operator()(const VDSymbol& s1, const VDSymbol& s2) const {
  56.             return s1.rva < s2.rva;
  57.         }
  58.     };
  59. }
  60.  
  61. VDSymbolSourceLinkMap::~VDSymbolSourceLinkMap() {
  62.     while(!mSymbols.empty()) {
  63.         VDSymbol& ent = mSymbols.back();
  64.  
  65.         free(ent.name);
  66.         mSymbols.pop_back();
  67.     }
  68. }
  69.  
  70. void VDSymbolSourceLinkMap::Init(const wchar_t *filename) {
  71.     if (const wchar_t *b = wcschr(filename, L'!')) {
  72.         std::wstring fn(filename, b - filename);
  73.  
  74.         VDFileStream fileStream(fn.c_str());
  75.         VDZipArchive zipArchive;
  76.  
  77.         zipArchive.Init(&fileStream);
  78.  
  79.         sint32 n = zipArchive.GetFileCount();
  80.         VDStringA name(VDTextWToA(b+1));
  81.  
  82.         for(int i=0; i<n; ++i) {
  83.             const VDZipArchive::FileInfo& fileInfo = zipArchive.GetFileInfo(i);
  84.  
  85.             if (fileInfo.mFileName == name) {
  86.                 IVDStream *pStream = zipArchive.OpenRawStream(i);
  87.  
  88.                 VDZipStream zipStream(pStream, fileInfo.mCompressedSize, !fileInfo.mbPacked);
  89.                 Init(&zipStream);
  90.                 return;
  91.             }
  92.         }
  93.  
  94.         throw "Can't find file in zip archive.";
  95.     }
  96.  
  97.     VDFileStream fileStream(filename);
  98.     Init(&fileStream);
  99. }
  100.  
  101. void VDSymbolSourceLinkMap::Init(IVDStream *pStream) {
  102.     VDTextStream textStream(pStream);
  103.  
  104.     mCodeSegments = 0;
  105.  
  106.     if (!findline(textStream, "Start         Length"))
  107.         throw "can't find segment list";
  108.  
  109.     while(const char *line = textStream.GetNextLine()) {
  110.         long grp, start, len;
  111.  
  112.         if (3!=sscanf(line, "%lx:%lx %lx", &grp, &start, &len))
  113.             break;
  114.  
  115.         if (strstr(line+49, "CODE")) {
  116.             printf("        %04x:%08lx %08lx type code (%dKB)\n", grp, start, len, (len+1023)>>10);
  117.  
  118.             mCodeSegments |= 1<<grp;
  119.  
  120.             mSections.push_back(VDSection(start, len, grp));
  121.         }
  122.     }
  123.  
  124.     if (!findline(textStream, "Publics by Value"))
  125.         throw "Can't find public symbol list.";
  126.  
  127.     textStream.GetNextLine();
  128.  
  129.     std::vector<sint64> groups;
  130.  
  131.     while(const char *line = textStream.GetNextLine()) {
  132.         long grp, start;
  133.         sint64 rva;
  134.         char symname[2048];
  135.  
  136.         // workaround for junk caused by VCPPCheck insertion with goofy anonymous namespace
  137.         if (strlen(line) > 21 && !strcmp(line+21, "?VCPPCheck@?% ")) {
  138.             textStream.GetNextLine();
  139.             textStream.GetNextLine();
  140.             textStream.GetNextLine();
  141.             textStream.GetNextLine();
  142.             textStream.GetNextLine();
  143.             textStream.GetNextLine();
  144.             textStream.GetNextLine();
  145.             continue;
  146.         }
  147.  
  148.         if (4!=sscanf(line, "%lx:%lx %s %I64x", &grp, &start, symname, &rva))
  149.             break;
  150.  
  151.         if (!(mCodeSegments & (1<<grp)))
  152.             continue;
  153.  
  154.         VDSymbol entry = { rva, grp, start, _strdup(symname) };
  155.  
  156.         if (groups.size() < (size_t)(grp+1))
  157.             groups.resize(grp+1, 0);
  158.  
  159.         if (!groups[grp])
  160.             groups[grp] = rva - start;
  161.  
  162.         mSymbols.push_back(entry);
  163.     }
  164.  
  165.     if (!findline(textStream, "Static symbols"))
  166.         printf("    warning: No static symbols found!\n");
  167.     else {
  168.         textStream.GetNextLine();
  169.  
  170.         while(const char *line = textStream.GetNextLine()) {
  171.             long grp, start;
  172.             sint64 rva;
  173.             char symname[4096];
  174.  
  175.             if (4!=sscanf(line, "%lx:%lx %s %I64x", &grp, &start, symname, &rva))
  176.                 break;
  177.  
  178.             if (!(mCodeSegments & (1<<grp)))
  179.                 continue;
  180.  
  181.             VDSymbol entry = { rva, grp, start, _strdup(symname) };
  182.  
  183.             if (groups.size() < size_t(grp+1))
  184.                 groups.resize(grp+1, 0);
  185.  
  186.             if (!groups[grp])
  187.                 groups[grp] = rva - start;
  188.  
  189.             mSymbols.push_back(entry);
  190.         }
  191.     }
  192.  
  193.     // parse line number information
  194.     const char *linefn = NULL;
  195.     int blanklines = 0;
  196.  
  197.     while(const char *line = textStream.GetNextLine()) {
  198.         if (!line[0] && linefn) {
  199.             if (!--blanklines)
  200.                 linefn = NULL;
  201.         }
  202.  
  203.         if (line[0] == 'L') {
  204.             if (!strncmp(line, "Line numbers for ", 17)) {
  205.                 const char *fnstart = line + 17;
  206.                 const char *fnend = fnstart;
  207.  
  208.                 while(const char c = *fnend) {
  209.                     if (c == '/' || c == '\\' || c == ':')
  210.                         fnstart = fnend+1;
  211.  
  212.                     if (c == '(')
  213.                         break;
  214.  
  215.                     ++fnend;
  216.                 }
  217.  
  218.                 mLineStrings.push_back(std::string(fnstart, fnend));
  219.                 linefn = mLineStrings.back().c_str();
  220.  
  221.                 // one blank line after the Line numbers header, one after the line numbers
  222.                 // themselves... so kill line number collection on the second blank line
  223.                 blanklines = 2;
  224.             }
  225.             continue;
  226.         }
  227.  
  228.         if (linefn && line[0] == ' ') {
  229.             int lineno[4], grp[4], offset[4];
  230.  
  231.             int count = sscanf(line, "%d %x:%x %d %x:%x %d %x:%x %d %x:%x"
  232.                 , &lineno[0], &grp[0], &offset[0]
  233.                 , &lineno[1], &grp[1], &offset[1]
  234.                 , &lineno[2], &grp[2], &offset[2]
  235.                 , &lineno[3], &grp[3], &offset[3]);
  236.  
  237.             if (count > 0) {
  238.                 count /= 3;
  239.                 for(int i=0; i<count; ++i)
  240.                     mLineMap.insert(tLineMap::value_type(groups[grp[i]] + offset[i], tLineInfo(linefn, lineno[i])));
  241.             }
  242.         }
  243.     }
  244.  
  245.     // rebias sections with group offsets
  246.     tSections::iterator it(mSections.begin()), itEnd(mSections.end());
  247.     for(; it!=itEnd; ++it) {
  248.         VDSection& sec = *it;
  249.  
  250.         if (size_t(sec.mGroup) < groups.size()) {
  251.             sec.mAbsStart = groups[sec.mGroup] + sec.mStart;
  252.         } else {
  253.             printf("    warning: no symbol found for group %u\n", sec.mGroup);
  254.             sec.mAbsStart = 0;
  255.         }
  256.     }
  257.  
  258.     // sort symbols
  259.     std::sort(mSymbols.begin(), mSymbols.end(), SymbolSort());
  260. }
  261.  
  262. const VDSymbol *VDSymbolSourceLinkMap::LookupSymbol(sint64 addr) {
  263.     VDSymbol s={addr, NULL};
  264.  
  265.     tSymbols::iterator it(std::upper_bound(mSymbols.begin(), mSymbols.end(), s, SymbolSort()));
  266.  
  267.     if (it == mSymbols.begin())
  268.         return NULL;
  269.  
  270.     return &*--it;
  271. }
  272.  
  273. const VDSection *VDSymbolSourceLinkMap::LookupSection(sint64 addr) {
  274.     return NULL;
  275. }
  276.  
  277. void VDSymbolSourceLinkMap::GetAllSymbols(vdfastvector<VDSymbol>& syms) {
  278.     syms = mSymbols;
  279. }
  280.  
  281. uint32 VDSymbolSourceLinkMap::GetCodeGroupMask() {
  282.     return mCodeSegments;
  283. }
  284.  
  285. int VDSymbolSourceLinkMap::GetSectionCount() {
  286.     return mSections.size();
  287. }
  288.  
  289. const VDSection *VDSymbolSourceLinkMap::GetSection(int sec) {
  290.     return &mSections[sec];
  291. }
  292.  
  293. bool VDSymbolSourceLinkMap::LookupLine(sint64 addr, const char *& filename, int& lineno) {
  294.     tLineMap::iterator it(mLineMap.upper_bound(addr));
  295.  
  296.     if (it != mLineMap.begin()) {
  297.         --it;
  298.  
  299.         filename = (*it).second.first;
  300.         lineno = (*it).second.second;
  301.         return true;
  302.     }
  303.  
  304.     return false;
  305. }
  306.